#include <vector>
#ifndef BASE
#define BASE
#include "base.cpp"
#endif

using namespace std;



const uint8_t const_utf8_tag = 1, const_integer_tag = 3, const_float_tag = 4,
const_long_tag = 5,const_double_tag = 6, const_class_tag = 7, const_string_tag = 8,
const_fieldref_tag = 9, const_methodref_tag = 10, const_interfaceMethodref_tag = 11,
const_nameAndType_tag = 12,const_MethodHandle_tag = 15, const_methodType_tag = 16,
const_InvokeDynamic_tag = 18;

const char* constant_tag_str[20];

class ConstantInfo {
public:
    uint8_t tag;
    int order;  // 序号
    virtual void print(const vector<ConstantInfo*> *pool){};
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
};

class ConstantUtf8Info : public ConstantInfo {
    public:
    uint16_t length;
    const string *bytes;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){
        return bytes;    
    };
    virtual void print( const vector<ConstantInfo*> *pool) {
        printf("   ");
        printf("#%d = %s", order, constant_tag_str[tag]);
        printf("          ");
        printf("%s", bytes->c_str());
        printf("\n");
    };
};

class ConstantIntegerInfo : public ConstantInfo {
    public:
    uint32_t *bytes;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantFloatInfo : public ConstantInfo {
    public:
    uint32_t *bytes;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print( const vector<ConstantInfo*> *pool){};
};

class ConstantLongInfo : public ConstantInfo {
    public:
    uint32_t *bytes;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantDoubleInfo : public ConstantInfo {
    public:
    uint32_t *bytes;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantClassInfo : public ConstantInfo{
    public:
    uint16_t index;
    
    virtual const string* printStr(const vector<ConstantInfo*> *pool) {
        ConstantUtf8Info* info =(ConstantUtf8Info*) (*pool)[index - 1];
        return info->bytes;
    }
    virtual void print(const vector<ConstantInfo*> *pool){
        printf("   ");
        printf("#%d = %s", order, constant_tag_str[tag]);
        printf("          ");
        printf("#%d", index);
        printf("            ");
        printf("// %s", printStr(pool)->c_str());
        printf("\n");
    };
};

class ConstantStringInfo : public ConstantInfo {
    public:
    uint16_t index;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){
        return NULL;
    };
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantFieldrefInfo : public ConstantInfo {
    public:
    uint16_t clsIdx;
    uint16_t typeIdx;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){
        return NULL;
    };
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantMethodrefInfo : public ConstantInfo {
    public:
    uint16_t clsIdx;
    uint16_t typeIdx;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){
        const string* clsStr = ((*pool)[clsIdx - 1])->printStr(pool);
        const string* typeStr = ((*pool)[typeIdx - 1])->printStr(pool);
        return NewOrFindString(*clsStr + "." + *typeStr);
    };
    virtual void print(const vector<ConstantInfo*> *pool){
        printf("   ");
        printf("#%d = %s", order, constant_tag_str[tag]);
        printf("          ");
        printf("#%d.#%d", clsIdx, typeIdx);
        printf("            ");
        
        printf("// %s", printStr(pool)->c_str());
        printf("\n");
    };
};

class ConstantInterfaceMethodrefInfo : public ConstantInfo {
    public:
    uint16_t clsIdx;
    uint16_t typeIdx;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantNameAndTypeInfo : public ConstantInfo {
    public:
    uint16_t idx1;
    uint16_t idx2;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){
        const string* idx1Str = (*pool)[idx1 - 1]->printStr(pool);
        const string* idx2Str = (*pool)[idx2 - 1]->printStr(pool);
        return NewOrFindString(*idx1Str + "." + *idx2Str);
    };
    virtual void print(const vector<ConstantInfo*> *pool){
        printf("   ");
        printf("#%d = %s", order, constant_tag_str[tag]);
        printf("          ");
        printf("#%d.#%d", idx1, idx2);
        printf("            ");
        
        printf("// %s", printStr(pool)->c_str());
        printf("\n");
    };
};


class ConstantMethodHandleInfo : public ConstantInfo {
    public:
    uint8_t ref_kind;
    uint16_t ref_idx;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantMethodTypeInfo : public ConstantInfo {
    public:
    uint16_t descriptor_idx;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print(const vector<ConstantInfo*> *pool){};
};

class ConstantDynamicInfo : public ConstantInfo {
    public:
    uint16_t bootstrap_method_attr_index;
    uint16_t name_and_type_idx;
    virtual const string* printStr(const vector<ConstantInfo*> *pool){return NULL;};
    virtual void print(const vector<ConstantInfo*> *pool){};
};